using System.Collections.Generic;

namespace Engine.FileFormats3D.WR2TrafficFiles
{
    public class SplineFileBlock
    {
        #region Public Fields

        public List<Spline> splines = new List<Spline>();

        #endregion Public Fields

        #region Public Methods

        public void AddStreet(int nodeStart, int nodeEnd, int usedSpeedBlock, float tangentLengthStart, float tangentLengthEnd, float streetLength, short crossroad, int crossID, TurnType turnType)
        {
            int splineID = splines.Count;
            int OppositeStreet = GetOppositeStreet(splineID, nodeStart, nodeEnd);

            short previewStreet = GetPreviewStreet(nodeStart, splineID, OppositeStreet);
            short nextStreet = GetNextStreet(splineID, nodeEnd, OppositeStreet);
            if (crossroad == 1 && nextStreet != -1)
            {
                this.splines[nextStreet].previewSpline = -1;
            }
            short numberOfWays = GetNumberOFWays(splineID, nodeEnd);
            if (nextStreet == OppositeStreet && nextStreet != -1)
            {
            }
            splines.Add(new Spline(splineID, (short)nodeStart, (short)nodeEnd, (short)usedSpeedBlock, tangentLengthStart, tangentLengthEnd, streetLength, crossroad, (short)OppositeStreet, (short)previewStreet, (short)nextStreet, (short)numberOfWays, crossID, turnType));

            //UpdateNumberOfWays();
        }

        public bool ContainsLeftLane(int nodeStart)
        {
            for (int i = 0; i < splines.Count; i++)
            {
                if (splines[i].nodeEnd2 == nodeStart)
                {
                    return true;
                }
            }
            return false;
        }

        public bool ContainsRightLane(int nodeEnd)
        {
            for (int i = 0; i < splines.Count; i++)
            {
                if (splines[i].nodestart1 == nodeEnd)
                {
                    return true;
                }
            }

            return false;
        }

        public short Count()
        {
            return (short)splines.Count;
        }

        public void Save(System.IO.BinaryWriter bw)
        {
            foreach (Spline spline in this.splines)
            {
                spline.Save(bw);
            }
        }

        public void UpdateNumberOfWays(int numberOFNodes)
        {
            for (int i = 0; i < this.splines.Count; i++)
            {
                int startNode = this.splines[i].nodestart1;
                int endNode = this.splines[i].nodeEnd2;

                int count = 0;
                if (this.splines[i].crossroad == 0)
                {
                    for (int next = 0; next < this.splines.Count; next++)
                    {
                        if (this.splines[next].nodestart1 == endNode && this.splines[next].nodeEnd2 != startNode)
                        {
                            count++;
                            //if (this.splines[next].crossID != -1)
                            //{
                            //}
                            //else if (this.splines[i].crossID != -1)
                            //{
                            //    count++;
                            //}
                        }
                    }
                }
                else
                {
                    count = 1;
                }
                this.splines[i].numWays = (short)count;
            }

            //Get the Count of streets which start with this Node
            //for (int nodeStart = 0; nodeStart < numberOFNodes; nodeStart++)
            //{
            //int count = 0;

            //    for (int sp = 0; sp < this.splines.Count; sp++)
            //    {
            //        if (this.splines[sp].nodestart1 == nodeStart)
            //        {
            //            count++;
            //        }
            //    }
            //    for (int sp = 0; sp < this.splines.Count; sp++)
            //    {
            //        if (this.splines[sp].nodeEnd2 == nodeStart)
            //        {
            //            this.splines[sp].numWays = (short)count;
            //        }
            //    }
            //}
        }

        #endregion Public Methods

        #region Private Methods

        private short GetNextStreet(int splineID, int nodeEnd, int oppositeStreet)
        {
            for (int sp = 0; sp < this.splines.Count; sp++)
            {
                if (oppositeStreet != sp && splines[sp].nodestart1 == nodeEnd)
                {
                    if (splines[sp].previewSpline == -1)
                    {
                        this.splines[sp].previewSpline = (short)splineID;
                    }
                    return (short)sp;
                }
            }
            return -1;
        }

        private short GetNumberOFWays(int splineID, int nodeEnd)
        {
            int countWays = 0;
            for (int sp = 0; sp < this.splines.Count; sp++)
            {
                if (sp != splineID)
                {
                    if (this.splines[sp].nodestart1 == nodeEnd)
                    {
                        countWays++;
                    }
                }
            }
            return (short)countWays;
        }

        private int GetOppositeStreet(int splineID, int nodeStart, int nodeEnd)
        {
            for (int sp = 0; sp < this.splines.Count; sp++)
            {
                if ((splines[sp].nodestart1 == nodeEnd) && (splines[sp].nodeEnd2 == nodeStart))
                {
                    if (splines[sp].oppositeLane == -1)
                    {
                        splines[sp].oppositeLane = (short)splineID;
                    }
                    return sp;
                }
            }
            return -1;
        }

        private short GetPreviewStreet(int nodeStart, int splineID, int oppositeStreet)
        {
            for (int sp = 0; sp < this.splines.Count; sp++)
            {
                if (oppositeStreet != sp && splines[sp].nodeEnd2 == nodeStart)
                {
                    if (splines[sp].nextSpline == -1)
                    {
                        splines[sp].nextSpline = (short)splineID;
                    }
                    return (short)sp;
                }
            }
            return -1;
        }

        #endregion Private Methods
    }
}